package de.bazinga.rotw.info;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Vector;

import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.InputHandler;
import com.jme.input.MouseInput;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.game.state.BasicGameState;
import com.jmex.game.state.GameState;

import de.bazinga.rotw.game.Game;
import de.bazinga.rotw.menu.Menu;


/**
 * Shows a Window with a given Info-Message.
 * You can set the text with {@link #addInfoText(String)}.
 * The Window will be disabled if the user clicks somewhere
 * 
 * @author Dennis Franke
 *
 */
public class InfoWindow extends BasicGameState {
	private Quad stat = null;
	
	/**
	 * The Texture for the Quad
	 */
	private TextureState infoTex;
	private Texture texture;
	
	
	/**
	 * This Vector contains all the Messages
	 * Every entry is a new Line
	 */
	private Vector<String> infoText = new Vector<String>();
	
	/**
	 * When did the state got activated?
	 * (We need this so we can make the user wait at least 1sek)
	 */
	private long activated = 0;
	

	/**
	 * the Mouse + Inputhandler
	 */
	private AbsoluteMouse am = null;
	private InputHandler input = new InputHandler();


	public InfoWindow() {
		super("infoWindow");
		
		init();
	}
	
	
	/**
	 * initializes the GameState
	 */
	private void init() {
		stat = new Quad("stat",
				Game.getGame().getDisplay().getWidth() - 100,
				Game.getGame().getDisplay().getHeight() - 100);
		
		
		redraw();

		
		stat.setRenderQueueMode(Renderer.QUEUE_ORTHO);
		
		stat.setLocalTranslation(new Vector3f(
				Game.getGame().getDisplay().getWidth()/2.0f,
				Game.getGame().getDisplay().getHeight()/2.0f,
				1));
		
		stat.setRenderState(infoTex);
		
		
		BlendState bs = Game.getGame().getDisplay().getRenderer().createBlendState();
		bs.setBlendEnabled(true);
		bs.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
		bs.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
		bs.setTestEnabled(true);
		bs.setTestFunction(BlendState.TestFunction.GreaterThan);
		
		stat.setRenderState(bs);
		
		stat.setLightCombineMode(Spatial.LightCombineMode.Off);
		stat.updateRenderState();
		
		getRootNode().attachChild(stat);
		

		
		initMouse();
	}
	
	
	/**
	 * Init the Mouse
	 */
	private void initMouse() {
		am = new AbsoluteMouse("Mouse",
				Game.getGame().getDisplay().getWidth(),
				Game.getGame().getDisplay().getHeight());
		
		
		TextureState cursor = Game.getGame().getDisplay().getRenderer().createTextureState();
        cursor.setEnabled(true);
        cursor.setTexture(TextureManager.loadTexture(Menu.class
                .getClassLoader().getResource("cursor/cursor.png"),
                Texture.MinificationFilter.BilinearNearestMipMap,
                Texture.MagnificationFilter.Bilinear));
        am.setRenderState(cursor);
		
		BlendState bs = Game.getGame().getDisplay().getRenderer().createBlendState();
		bs.setBlendEnabled(true);
		bs.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
		bs.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
		bs.setTestEnabled(true);
		bs.setTestFunction(BlendState.TestFunction.GreaterThan);
		
		am.setRenderState(bs);
		
		
		// Get the mouse input device and assign it to the AbsoluteMouse
        // Move the mouse to the middle of the screen to start with
        am.setLocalTranslation(
        		new Vector3f(
        				Game.getGame().getDisplay().getWidth() / 2, 
        				Game.getGame().getDisplay().getHeight() / 2, 
        				0)
        		);
        // Assign the mouse to an input handler
        am.registerWithInputHandler( input );
 
        
        am.updateRenderState();
		
		getRootNode().attachChild(am);
	}
	
	
	
	/**
	 * Updates the rootNode.
	 * 
	 * @see GameState#update(float)
	 */
	public void update(float tpf) {
		if((System.currentTimeMillis() - activated) < 1000) return;
		
		super.update(tpf);
		
		// Disable if user clicked mouse-button
		if(MouseInput.get().isButtonDown(0)) {
			this.setActive(false);
		}
		
		input.update(tpf);
	}
	


	/**
	 * Draws the rootNode.
	 * 
	 * @see GameState#render(float)
	 */
	public void render(float tpf) {
		super.render(tpf);
	}
	
	
	/**
	 * Overwrite so we can save the activated-Time
	 */
	public void setActive(boolean active) {
		activated = System.currentTimeMillis();
		super.setActive(active);
	}
	
	
	/**
	 * Redraw the Texture
	 */
	private void redraw() {
		//Texture
		infoTex = Game.getGame().getDisplay().getRenderer().createTextureState();
		texture = TextureManager.loadTexture(getBufferedImage(),
				Texture.MinificationFilter.BilinearNearestMipMap , 
				Texture.MagnificationFilter.Bilinear,
				false);
			
		infoTex.setTexture(texture);
		infoTex.setEnabled(true);
			
		stat.setRenderState(infoTex);
		stat.updateRenderState();		
	}
	
	
	/**
	 * Create a BufferedImage with the infoText on it
	 * @return the BufferedImage with the infoText on it
	 */
	private BufferedImage getBufferedImage() {
		BufferedImage img = new BufferedImage(512,512,BufferedImage.TYPE_INT_ARGB);
		
		Graphics2D g = img.createGraphics();
		
		g.setColor(new Color(150,150, 150, 100));
		g.fillRect(0, 0, img.getWidth(), img.getHeight());
		
		g.setColor(Color.black);
		g.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
		
		g.setColor(Color.black);
		
		g.setFont(new Font("Arial", Font.BOLD, 30));
		
		int c = 0;
		for(String info:infoText) {
			g.drawString(info, 50, 50 + c*50);
			c++;
		}
		
		
		
		BufferedImage mirror = new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_INT_ARGB);
		for(int i=0;i<512;i++) {
			for(int j=0;j<512;j++) {
				mirror.setRGB(i, img.getHeight() - j - 1, img.getRGB(i, j));
			}
		}
		
		return mirror;
	}

	
	/**
	 * Get the Info-Text
	 * @return Retuns the Vector with the info-Text
	 */
	public Vector<String> getInfoText() {
		return infoText;
	}


	/**
	 * Set the infoText
	 * @param infoText the new infoText. Every entry is a new line
	 */
	public void setInfoText(Vector<String> infoText) {
		this.infoText = infoText;
		redraw();
	}
	
	public void clearInfoText() {
		infoText.clear();
	}
	
	public void addInfoText(String text) {
		infoText.add(text);
		redraw();
	}
}